package io.github.howiefh.cas.authentication;

import com.yiper.util.PasswordHelper;
import org.jasig.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.HandlerResult;
import org.jasig.cas.authentication.PreventedException;
import org.jasig.cas.authentication.UsernamePasswordCredential;
import org.jasig.cas.authentication.principal.SimplePrincipal;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;

import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.FailedLoginException;
import javax.sql.DataSource;
import javax.validation.constraints.NotNull;
import java.security.GeneralSecurityException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Administrator on 2018/9/13.
 */
public class YiperQueryDBAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
    private static final String DEFAULT_PASSWORD_FIELD = "password";
    Long userid;
    /**
     * The Algorithm name.
     */
    int result = 0;

    @NotNull
    protected final String sql;

    @NotNull
    protected final String sql_email;

    /**
     * The Password field name.
     */
    @NotNull
    protected String passwordFieldName = DEFAULT_PASSWORD_FIELD;

    /**
     * Instantiates a new Query and encode database authentication handler.
     *  @param datasource
     *            The database datasource
     * @param sql
     *            the sql query to execute which must include a parameter
     *            placeholder for the user id. (i.e.
     *            <code>SELECT * FROM table WHERE username = ?</code>
     *            the algorithm name (i.e.
     * @param sql_email
     */

    public YiperQueryDBAuthenticationHandler(final DataSource datasource, final String sql, final String sql_email) {
        super();
        setDataSource(datasource);
        this.sql = sql;
        this.sql_email = sql_email;
    }

    @Override
    protected HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential transformedCredential) throws GeneralSecurityException, PreventedException {
        final String username = getPrincipalNameTransformer().transform(transformedCredential.getUsername());
        result = 0;
        String accountString = "";
        //电子邮件
        String check = "^(?![_.])\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
        Pattern regex = Pattern.compile(check);
        //Matcher matcher = regex.matcher("dffdfdf@qq.co#m");
        Matcher matcher = regex.matcher(username);
        boolean isMatched = matcher.matches();
        if (isMatched) { // 如果是邮箱
            try {
                final Map<String, Object> values = getJdbcTemplate().queryForMap(this.sql_email, username);
                accountString = (String) values.get("username");
            } catch (Exception e) {
                result = 5;
                throw new AccountNotFoundException("email account not found.");
            }

        }else {
            try{
                final Map<String, Object> values = getJdbcTemplate().queryForMap(this.sql, username);
                accountString = (String) values.get("username");
            }catch (Exception e){
                result = 5;
                throw new AccountNotFoundException("account not found.");
            }
        }

        try{
            final Map<String, Object> values = getJdbcTemplate().queryForMap(this.sql, accountString);
            if (!verifyPassword((String) values.get(this.passwordFieldName), transformedCredential.getPassword())) {	//12345
                System.err.println("密码错误");
                throw new FailedLoginException(
                        "Password does not match value on record.");
            }

            //以邮箱方式登录 登录的还是通过userName和密码来校验
            transformedCredential.setUsername(accountString);
            return createHandlerResult(transformedCredential, new SimplePrincipal(username), null);
        } catch (final IncorrectResultSizeDataAccessException e) {
            if (e.getActualSize() == 0) {
                result = 1;
                throw new AccountNotFoundException(username
                        + " not found with SQL query");
            } else {
                result = 2;
                throw new FailedLoginException("Multiple records found for "
                        + username);
            }
        } catch (final DataAccessException e) {
            result = 3;
            throw new PreventedException(
                    "SQL exception while executing query for " + username, e);
        } finally {

        }

    }



/**/
    private boolean verifyPassword(String expected, String actual) {
        try {
            return PasswordHelper.VerifyHashedPassword(expected, actual);
        } catch (Exception e) {
            logger.error("Failed to verifyPassword", e);
            return false;
        }
    }

}
